// 改造koa-jwt以支持koa@2，否则用到的地方还要加convert，太麻烦
import jwt from 'jsonwebtoken';
import unless from 'koa-unless';

export default opts => {
    opts = opts || {};
    opts.key = opts.key || 'user';

    const middleware = async(ctx, next) => {
        let token, msg, user, parts, scheme, credentials;

        if (opts.getToken) {
            token = opts.getToken.call(ctx);
        } else if (opts.cookie && ctx.cookies.get(opts.cookie)) {
            token = ctx.cookies.get(opts.cookie);
        } else if (ctx.header.authorization) {
            parts = ctx.header.authorization.split(' ');
            if (parts.length === 2) {
                scheme = parts[0];
                credentials = parts[1];
                if (/^Bearer$/i.test(scheme)) {
                    token = credentials;
                }
            } else if (!opts.passthrough) {
                ctx.throw(401, 'Bad Authorization header format');
            }
        } else if (!opts.passthrough) {
            ctx.throw(401, 'No Authorization header found\n');
        }

        const secret = (ctx.state && ctx.state.secret) ? ctx.state.secret : opts.secret;
        if (!secret) {
            ctx.throw(500, 'Invalid secret\n');
        }

        try {
            user = jwt.verify(token, secret, opts);
        } catch (e) {
            msg = 'Invalid token' + (opts.debug ? ' - ' + e.message + '\n' : '\n');
        }

        if (user || opts.passthrough) {
            ctx.state = ctx.state || {};
            ctx.state[opts.key] = user;
            ctx.request[opts.key] = user;
            await next();
        } else {
            ctx.throw(401, msg);
        }
    };

    middleware.unless = unless;
    return middleware;
};
